using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using ShapeRenderingSample;
using BEPUphysics;
using BEPUphysics.Entities;
using BEPUphysics.Entities.Prefabs;
using BEPUphysics.Materials;

namespace ChimneySim
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        
        private MainForm form;

        private SpriteFont font;
        private float x;
        private float y;
        private float xLastState, yLastState;
        private bool firstClick = true;
        private bool zoomClick = true;


        private Matrix worldMatrix, viewMatrix, projectionMatrix;
        private ArcBallCamera camera;

        private Chimney chimney;
        private World world;
        private Room room;
        private ParticleEmitter emmiter;

        float gapH = 0.25f;

        private BasicEffect basicEffect;

        //Billboards
        private List<Billboard> billboards;
        private Effect billboardEffect;
        private Texture2D billboardTexture;

        //Bepu
        Space space;

        public Game1(MainForm form)
        {
            this.form = form;

            graphics = new GraphicsDeviceManager(this)
            {
                PreferredBackBufferWidth = form.CanvasSize.Width,
                PreferredBackBufferHeight = form.CanvasSize.Height
            };

            graphics.PreparingDeviceSettings += graphics_PreparingDeviceSettings;
            System.Windows.Forms.Control.FromHandle(Window.Handle).VisibleChanged += MainGame_VisibleChanged;
            Mouse.WindowHandle = form.Canvas.Handle;

            wallThickness = (float)form.wallThicknessNB.Value;
            roomWallThickness = (float)form.roomWallNB.Value;

            Content.RootDirectory = "Content";
        }

        #region Form functions

        void MainGame_VisibleChanged(object sender, System.EventArgs e)
        {
            if (System.Windows.Forms.Control.FromHandle(Window.Handle).Visible)
                System.Windows.Forms.Control.FromHandle(Window.Handle).Visible = false;
        }

        void graphics_PreparingDeviceSettings(object sender, PreparingDeviceSettingsEventArgs e)
        {
            e.GraphicsDeviceInformation.PresentationParameters.DeviceWindowHandle = form.CanvasHandle;
        }

        #endregion

        #region Event handlers

        void roomZNB_ValueChanged(object sender, EventArgs e)
        {
            room.roomLeft.Min.Z = (float)form.roomZNB.Value + roomWallThickness;
            room.roomLeft.Max.Z = (float)form.roomZNB.Value + roomWallThickness * 2;
            room.roomFront.Max.Z = (float)form.roomZNB.Value + roomWallThickness * 2;
            room.roomBack.Max.Z = (float)form.roomZNB.Value + roomWallThickness * 2;
            room.roomTop.Max.Z = (float)form.roomZNB.Value + roomWallThickness * 2;

            UpdateRoom();
        }

        void roomYNB_ValueChanged(object sender, EventArgs e)
        {
            room.roomLeft.Max.Y = (float)form.roomYNB.Value;
            room.roomRight.Max.Y = (float)form.roomYNB.Value;
            room.roomFront.Max.Y = (float)form.roomYNB.Value;
            room.roomBack.Max.Y = (float)form.roomYNB.Value;
            room.roomTop.Min.Y = (float)form.roomYNB.Value;
            room.roomTop.Max.Y = (float)form.roomYNB.Value + roomWallThickness;

            UpdateRoom();
        }

        void roomXNB_ValueChanged(object sender, EventArgs e)
        {
            room.roomLeft.Max.X = (float)form.roomXNB.Value;
            room.roomRight.Max.X = (float)form.roomXNB.Value;
            room.roomRight2.Max.X = (float)form.roomXNB.Value;
            room.roomFront.Min.X = (float)form.roomXNB.Value;
            room.roomFront.Max.X = (float)form.roomXNB.Value + roomWallThickness;
            room.roomTop.Max.X = (float)form.roomXNB.Value + roomWallThickness;

            UpdateRoom();
        }

        void roomWallNB_ValueChanged(object sender, EventArgs e)
        {
            this.roomWallThickness = (float)form.roomWallNB.Value;

            room.roomLeft = new BoundingBox(new Vector3(0, 0, (float)form.roomZNB.Value + roomWallThickness), new Vector3((float)form.roomXNB.Value, (float)form.roomYNB.Value, (float)form.roomZNB.Value + roomWallThickness * 2));
            room.roomRight = new BoundingBox(new Vector3(0, gapH, 0), new Vector3((float)form.roomXNB.Value, (float)form.roomYNB.Value, roomWallThickness));
            room.roomRight2 = new BoundingBox(new Vector3(chimney.chimneyLeft.Max.X, 0, 0), new Vector3((float)form.roomXNB.Value, gapH, roomWallThickness));
            room.roomFront = new BoundingBox(new Vector3((float)form.roomXNB.Value, 0, 0), new Vector3((float)form.roomXNB.Value + roomWallThickness, (float)form.roomYNB.Value, (float)form.roomZNB.Value + roomWallThickness * 2));
            room.roomBack = new BoundingBox(new Vector3(0), new Vector3(-roomWallThickness, (float)form.roomYNB.Value, (float)form.roomZNB.Value + roomWallThickness * 2));
            room.roomTop = new BoundingBox(new Vector3(-roomWallThickness, (float)form.roomYNB.Value, 0), new Vector3((float)form.roomXNB.Value + roomWallThickness, (float)form.roomYNB.Value + roomWallThickness, (float)form.roomZNB.Value + roomWallThickness * 2));

            UpdateRoom();        
        }

        void chimneyXNB_ValueChanged(object sender, EventArgs e)
        {
            chimney.chimneyLeft.Max.X = (float)form.chimneyXNB.Value;
            room.roomRight2.Min.X = chimney.chimneyLeft.Max.X;
            chimney.chimneyRight.Max.X = (float)form.chimneyXNB.Value;
            chimney.chimneyFront.Min.X = (float)form.chimneyXNB.Value;
            chimney.chimneyFront.Max.X = (float)form.chimneyXNB.Value + wallThickness;


            emmiter.Position = new Vector3((chimney.chimneyLeft.Min.X + chimney.chimneyRight.Max.X) / 2, 0.5f, (chimney.chimneyFront.Min.Z + chimney.chimneyBack.Max.Z) / 2);

            UpdateChimney();
            UpdateRoom();
        }

        void chimneyYNB_ValueChanged(object sender, EventArgs e)
        {
            chimney.chimneyLeft.Max.Y = (float)form.chimneyYNB.Value;
            chimney.chimneyRight.Max.Y = (float)form.chimneyYNB.Value;
            chimney.chimneyFront.Max.Y = (float)form.chimneyYNB.Value;
            chimney.chimneyBack.Max.Y = (float)form.chimneyYNB.Value;

            UpdateChimney();
        }

        void chimneyZNB_ValueChanged(object sender, EventArgs e)
        {
            chimney.chimneyRight.Min.Z = -(float)form.chimneyZNB.Value - wallThickness;
            chimney.chimneyRight.Max.Z = -(float)form.chimneyZNB.Value - (wallThickness * 2);
            chimney.chimneyFront.Max.Z = -(float)form.chimneyZNB.Value - (wallThickness * 2);
            chimney.chimneyBack.Max.Z = -(float)form.chimneyZNB.Value - (wallThickness * 2);

            emmiter.Position = new Vector3((chimney.chimneyLeft.Min.X + chimney.chimneyRight.Max.X) / 2, 0.5f, (chimney.chimneyFront.Min.Z + chimney.chimneyBack.Max.Z) / 2);

            UpdateChimney();
        }

        void wallThicknessNB_ValueChanged(object sender, EventArgs e)
        {
            this.wallThickness = (float)form.wallThicknessNB.Value;

            chimney.chimneyLeft = new BoundingBox(new Vector3(0, gapH, 0), new Vector3((float)form.chimneyXNB.Value, (float)form.chimneyYNB.Value, -wallThickness));
            chimney.chimneyRight = new BoundingBox(new Vector3(0.0f, 0.0f, -(float)form.chimneyZNB.Value - wallThickness), new Vector3((float)form.chimneyXNB.Value, (float)form.chimneyYNB.Value, -(float)form.chimneyZNB.Value - (wallThickness * 2)));
            chimney.chimneyFront = new BoundingBox(new Vector3((float)form.chimneyXNB.Value, 0, 0), new Vector3((float)form.chimneyXNB.Value + wallThickness, (float)form.chimneyYNB.Value, -(float)form.chimneyZNB.Value - (wallThickness * 2)));
            chimney.chimneyBack = new BoundingBox(new Vector3(0), new Vector3(-wallThickness, (float)form.chimneyYNB.Value, -(float)form.chimneyZNB.Value - (wallThickness * 2)));

            UpdateChimney();
        }  

        void windX_ValueChanged(object sender, EventArgs e)
        {
            world.windSpeed.X = (float)form.windXNB.Value;
        }

        void windY_ValueChanged(object sender, EventArgs e)
        {
            world.windSpeed.Y = (float)form.windYNB.Value;
        }

        void windZ_ValueChanged(object sender, EventArgs e)
        {
            world.windSpeed.Z = (float)form.windZNB.Value;
        }

        #endregion

        float wallThickness;
        float roomWallThickness;

        protected override void Initialize()
        {
            // TODO: Add your initialization logic here
            IsMouseVisible = true;

            oldMouseState = Mouse.GetState();
            oldKeyboardState = Keyboard.GetState();

            worldMatrix = Matrix.Identity;
            viewMatrix = Matrix.CreateLookAt(new Vector3(0, 10, 10), Vector3.Zero, Vector3.Up);
            projectionMatrix = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(60.0f), 4.0f / 3.0f, 0.3f, 100.0f);

            DebugShapeRenderer.Initialize(GraphicsDevice);

            camera = new ArcBallCamera(MathHelper.ToRadians(60.0f), (float)graphics.PreferredBackBufferWidth, (float)graphics.PreferredBackBufferHeight, 0.101f, 10000.0f);

            xLastState = Mouse.GetState().X;
            yLastState = Mouse.GetState().Y;

            world = new World(form);
            room = new Room(form, world);
            chimney = new Chimney(form, world, room);

            //Bepu
            InitializeBepuPhysics();
            CreateBepuGround();

            CreateRoom();
            CreateChimney();

            /*Event handlers*/
            form.roomXNB.ValueChanged += new EventHandler(roomXNB_ValueChanged);
            form.roomYNB.ValueChanged += new EventHandler(roomYNB_ValueChanged);
            form.roomZNB.ValueChanged += new EventHandler(roomZNB_ValueChanged);
            form.roomWallNB.ValueChanged += new EventHandler(roomWallNB_ValueChanged);
            form.chimneyXNB.ValueChanged += new EventHandler(chimneyXNB_ValueChanged);
            form.chimneyYNB.ValueChanged += new EventHandler(chimneyYNB_ValueChanged);
            form.chimneyZNB.ValueChanged += new EventHandler(chimneyZNB_ValueChanged);
            form.wallThicknessNB.ValueChanged += new EventHandler(wallThicknessNB_ValueChanged);
            form.windXNB.ValueChanged += new EventHandler(windX_ValueChanged);
            form.windYNB.ValueChanged += new EventHandler(windY_ValueChanged);
            form.windZNB.ValueChanged += new EventHandler(windZ_ValueChanged);

            basicEffect = new BasicEffect(graphics.GraphicsDevice);            

            emmiter = new ParticleEmitter(space, new Vector3(0.2f, 0.5f, -0.2f), new Vector3(0, 0, 0), 500);
            //emmiter = new ParticleEmitter(physics, scene, new Px.Math.Vector3(0.2f, 0.2f, 0.2f), new Px.Math.Vector3(0, 0, 0), 100);
            emmiter.RandPosMaxVal = 0.05f;
            emmiter.RandVelMaxVal = 1.0f;
            //emmiter.SpawnRigidParticle();
            //emmiter.SpawnParticle();
            //emmiter.CreateParticles();
            emmiter.EmmisionRate = 50;            
            //emmiter.ParticleSystem.ParticleMass = 0.001f;
            
            //emmiter.ParticleSystem.ExternalAcceleration = new Px.Math.Vector3(0, 10, 0);

            billboards = new List<Billboard>();

            base.Initialize();
        }

        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);

            // TODO: use this.Content to load your game content here
            font = Content.Load<SpriteFont>("hudFont");

            Model particleModel = Content.Load<Model>("particle");
            emmiter.Model = particleModel;

            billboardTexture = Content.Load<Texture2D>("smoketex");
            billboardEffect = Content.Load<Effect>("BillboardEffect");
        }

        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        MouseState currentMouseState, oldMouseState;
        KeyboardState currentKeyboardState, oldKeyboardState;

        protected override void Update(GameTime gameTime)
        {
            world.Refresh();
            room.Refresh();
            chimney.Refresh();
            // Allows the game to exit
            oldMouseState = currentMouseState;
            currentMouseState = Mouse.GetState();

            oldKeyboardState = currentKeyboardState;
            currentKeyboardState = Keyboard.GetState();

            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                this.Exit();

            if (Mouse.GetState().LeftButton == ButtonState.Pressed)
            {
                x = Mouse.GetState().X;
                y = Mouse.GetState().Y;

                if (firstClick)
                {
                    xLastState = x;
                    yLastState = y;
                    firstClick = false;
                }

                float xDelta = (xLastState - x) * 0.5f;
                float yDelta = (yLastState - y) * 0.5f;

                camera.HorizontalAngle += MathHelper.ToRadians(xDelta);
                camera.VerticalAngle += MathHelper.ToRadians(yDelta);
                //camera.Update(gameTime);

                xLastState = x;
                yLastState = y;
            }

            if (Mouse.GetState().LeftButton == ButtonState.Released)
            {
                firstClick = true;
            }
            camera.Update(gameTime);
            //camera.Zoom = (float)Mouse.GetState().ScrollWheelValue;
            
            if (Mouse.GetState().RightButton == ButtonState.Pressed)
            {
                x = Mouse.GetState().X;
                y = Mouse.GetState().Y;

                if (zoomClick)
                {
                    xLastState = x;
                    yLastState = y;
                    zoomClick = false;
                }

                float xDelta = (xLastState - x) * 0.5f;
                float yDelta = (yLastState - y) * 1.5f;

                //camera.HorizontalAngle += MathHelper.ToRadians(xDelta);
                //camera.VerticalAngle += MathHelper.ToRadians(yDelta);
                camera.Zoom += yDelta;
                //camera.Update(gameTime);                

                xLastState = x;
                yLastState = y;
            }

            if (Mouse.GetState().RightButton == ButtonState.Released)
            {
                zoomClick = true;
            }

            emmiter.Update(gameTime);


            List<Vector3> particleForces = new List<Vector3>();
            List<int> indexes = new List<int>();
            List<Vector3> windVelocities = new List<Vector3>();
            List<int> windIndexes = new List<int>();
            billboards.Clear();

            for (int i = 0; i < emmiter.PPositions.Count; i++)
            {
                Vector3 particlePosTmp = emmiter.PPositions[i];
                Vector3 particlePos = new Vector3(particlePosTmp.X, particlePosTmp.Y, particlePosTmp.Z);

                Vector3 billboardPos = new Vector3(particlePos.X - emmiter.Size,
                    particlePos.Y - emmiter.Size,
                    particlePos.Z);
                Billboard b = new Billboard(particlePos, billboardTexture, new Vector2(emmiter.Size * 2.0f, emmiter.Size * 2.0f), billboardEffect, GraphicsDevice);
                billboards.Add(b);

                if (chimney.chimneyAll.Contains(particlePos) == ContainmentType.Contains)
                {
                    float force = chimney.ActiveForceOnHeight(particlePos.Y);
                    particleForces.Add(new Vector3(0.01f, force, 0.01f));
                    indexes.Add(i);

                }
                else if (room.roomAll.Contains(particlePos) == ContainmentType.Contains)
                {
                    float force = room.ActiveForceOnHeight(particlePos.Y);
                    particleForces.Add(new Vector3(0.01f, force, 0.01f));
                    indexes.Add(i);                 
                }
                else
                {
                    float force = world.ActiveForceOnHeight(particlePos.Y);
                    //particleForces.Add(new PxM.Vector3(0.01f, force, 0.01f));
                    windVelocities.Add(new Vector3(world.windSpeed.X, world.windSpeed.Y, world.windSpeed.Z));
                    windIndexes.Add(i);                   
                }
            }

            emmiter.AddForces(particleForces, indexes);
            emmiter.AddLinearVelocity(windVelocities, windIndexes);

            
            space.Update();
            

            camera.Update(gameTime); 
            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.Black);

            spriteBatch.Begin();
            spriteBatch.DrawString(font, "Temperatura u szczytu komina: " + world.TemperatureOnHeight(chimney.chimneyLeft.Max.Y).ToString(), new Vector2(10, 10), Color.White);
            spriteBatch.DrawString(font, "Temperatura u podstawy komina: " + room.TemperatureOnHeight(0).ToString(), new Vector2(10, 30), Color.White);
            spriteBatch.End();

            DebugShapeRenderer.AddBoundingBox(room.roomLeft, Color.Yellow);
            DebugShapeRenderer.AddBoundingBox(room.roomRight, Color.Yellow);
            DebugShapeRenderer.AddBoundingBox(room.roomRight2, Color.Yellow);
            DebugShapeRenderer.AddBoundingBox(room.roomFront, Color.Yellow);
            DebugShapeRenderer.AddBoundingBox(room.roomBack, Color.Yellow);
            DebugShapeRenderer.AddBoundingBox(room.roomTop, Color.Yellow);

            DebugShapeRenderer.AddBoundingBox(chimney.chimneyLeft, Color.Yellow);
            DebugShapeRenderer.AddBoundingBox(chimney.chimneyRight, Color.Yellow);
            DebugShapeRenderer.AddBoundingBox(chimney.chimneyFront, Color.Yellow);
            DebugShapeRenderer.AddBoundingBox(chimney.chimneyBack, Color.Yellow);

            DebugShapeRenderer.AddBoundingBox(bepuGround.CollisionInformation.BoundingBox, Color.Red);
            

            /*DebugShapeRenderer.AddBoundingBox(room.roomAll, Color.Yellow);
            DebugShapeRenderer.AddBoundingBox(chimney.chimneyAll, Color.Yellow);*/

            foreach (Billboard b in billboards)
            {
                b.Draw(camera.viewMatrix, camera.projectionMatrix);
            }


            DebugShapeRenderer.AddBoundingSphere(new BoundingSphere(emmiter.Position, 0.05f), Color.Black);
            DebugShapeRenderer.Draw(gameTime, camera.viewMatrix, camera.projectionMatrix);
            
            /*foreach (Particle p in emmiter.Particles)
            {
                DrawParticle(p, camera.viewMatrix, camera.projectionMatrix);
            }*/
            //RenderBufferData(scene.GetRenderBuffer());
            

            base.Draw(gameTime);
        }

    /*    private void DrawParticle(Particle p, Matrix view, Matrix projection)
        {
            Model m = emmiter.Model;
            Matrix[] transforms = new Matrix[m.Bones.Count];
            m.CopyAbsoluteBoneTransformsTo(transforms);

            foreach (ModelMesh mesh in m.Meshes)
            {
                foreach (BasicEffect effect in mesh.Effects)
                {
                    effect.EnableDefaultLighting();

                    effect.View = view;
                    effect.Projection = projection;
                    effect.World = Matrix.CreateScale(0.001f) * transforms[mesh.ParentBone.Index] *
                        Matrix.CreateTranslation(emmiter.EmitterPosition)
                        * Matrix.CreateTranslation(p.Position);
                }
                mesh.Draw();
            }
        }*/

        #region BepuPhysics

        private void InitializeBepuPhysics()
        {
            space = new Space();
            space.ForceUpdater.Gravity = new Vector3(0, -9.81f, 0);

            if (Environment.ProcessorCount > 1)
            {
                for (int i = 0; i < Environment.ProcessorCount; i++)
                {
                    space.ThreadManager.AddThread();
                }
            }

            space.Solver.IterationLimit = 7;
        }

        private Box bepuGround;

        private void CreateBepuGround()
        {
            bepuGround = new Box(new Vector3(0, -0.01f, 0), 10, 0.02f, 10);
            bepuGround.Material = new BEPUphysics.Materials.Material(0.5f, 0.5f, 0.5f);
            space.Add(bepuGround);
        }

        #endregion


        #region Room and Chimney

        Box roomLeft;
        Box roomRight;
        Box roomRight2;
        Box roomFront;
        Box roomBack;
        Box roomTop;
        Material roomMaterial;

        Box chimneyLeft;
        Box chimneyRight;
        Box chimneyFront;
        Box chimneyBack;
        Material chimneyMaterial;

        bool roomCreated = false;
        bool chimneyCreated = false;

        

        private void CreateRoom()
        {
            room.roomLeft = new BoundingBox(new Vector3(0, 0, (float)form.roomZNB.Value + roomWallThickness), new Vector3((float)form.roomXNB.Value, (float)form.roomYNB.Value, (float)form.roomZNB.Value + roomWallThickness * 2));            
            room.roomRight = new BoundingBox(new Vector3(0, gapH, 0), new Vector3((float)form.roomXNB.Value, (float)form.roomYNB.Value, roomWallThickness));
            room.roomRight2 = new BoundingBox(new Vector3(chimney.chimneyLeft.Max.X, 0, 0), new Vector3((float)form.roomXNB.Value, gapH, roomWallThickness));
            room.roomFront = new BoundingBox(new Vector3((float)form.roomXNB.Value, 0, 0), new Vector3((float)form.roomXNB.Value + roomWallThickness, (float)form.roomYNB.Value, (float)form.roomZNB.Value + roomWallThickness * 2));
            room.roomBack = new BoundingBox(new Vector3(0), new Vector3(-roomWallThickness, (float)form.roomYNB.Value, (float)form.roomZNB.Value + roomWallThickness * 2));     
            room.roomTop = new BoundingBox(new Vector3(-roomWallThickness, (float)form.roomYNB.Value, 0), new Vector3((float)form.roomXNB.Value + roomWallThickness, (float)form.roomYNB.Value + roomWallThickness, (float)form.roomZNB.Value + roomWallThickness * 2));

            UpdateRoom();
            roomCreated = true;
       
        }

        private void CreateChimney()
        {
            chimneyMaterial = new Material(0.2f, 0.2f, 0.1f);
            
            chimney.chimneyLeft = new BoundingBox(new Vector3(0, gapH, 0), new Vector3((float)form.chimneyXNB.Value, (float)form.chimneyYNB.Value, -wallThickness));
            chimney.chimneyRight = new BoundingBox(new Vector3(0.0f, 0.0f, -(float)form.chimneyZNB.Value - wallThickness), new Vector3((float)form.chimneyXNB.Value, (float)form.chimneyYNB.Value, -(float)form.chimneyZNB.Value - (wallThickness * 2)));
            chimney.chimneyFront = new BoundingBox(new Vector3((float)form.chimneyXNB.Value, 0, 0), new Vector3((float)form.chimneyXNB.Value + wallThickness, (float)form.chimneyYNB.Value, -(float)form.chimneyZNB.Value - (wallThickness * 2)));
            chimney.chimneyBack = new BoundingBox(new Vector3(0), new Vector3(-wallThickness, (float)form.chimneyYNB.Value, -(float)form.chimneyZNB.Value - (wallThickness * 2)));

            UpdateChimney();
            chimneyCreated = true;
            
        }
        
        private void UpdateRoom()
        {
            Vector3 shape;
            
            if (roomCreated == true)
            {                
                space.Remove(roomLeft);
                space.Remove(roomRight);
                space.Remove(roomRight2);
                space.Remove(roomFront);
                space.Remove(roomBack);
                space.Remove(roomTop);
            }                
            

            shape = CalcuateBoxShape(room.roomLeft);
            roomLeft = new Box(CalculateBoxPosition(room.roomLeft), shape.X, shape.Y, shape.Z);
            space.Add(roomLeft);

            shape = CalcuateBoxShape(room.roomRight);
            roomRight = new Box(CalculateBoxPosition(room.roomRight), shape.X, shape.Y, shape.Z);
            space.Add(roomRight);

            shape = CalcuateBoxShape(room.roomRight2);
            roomRight2 = new Box(CalculateBoxPosition(room.roomRight2), shape.X, shape.Y, shape.Z);
            space.Add(roomRight2);
            
            shape = CalcuateBoxShape(room.roomFront);
            roomFront = new Box(CalculateBoxPosition(room.roomFront), shape.X, shape.Y, shape.Z);
            space.Add(roomFront);
            
            shape = CalcuateBoxShape(room.roomBack);
            roomBack = new Box(CalculateBoxPosition(room.roomBack), shape.X, shape.Y, shape.Z);
            space.Add(roomBack);

            shape = CalcuateBoxShape(room.roomTop);
            roomTop = new Box(CalculateBoxPosition(room.roomTop), shape.X, shape.Y, shape.Z);
            space.Add(roomTop);
        }

        private void UpdateChimney()
        {
            Vector3 shape;

            if (chimneyCreated == true)
            {
                space.Remove(chimneyLeft);
                space.Remove(chimneyRight);
                space.Remove(chimneyFront);
                space.Remove(chimneyBack);
            }
            

            shape = CalcuateBoxShape(chimney.chimneyLeft);
            chimneyLeft = new Box(CalculateBoxPosition(chimney.chimneyLeft), shape.X, shape.Y, shape.Z);
            space.Add(chimneyLeft);

            shape = CalcuateBoxShape(chimney.chimneyRight);
            chimneyRight = new Box(CalculateBoxPosition(chimney.chimneyRight), shape.X, shape.Y, shape.Z);
            space.Add(chimneyRight);

            shape = CalcuateBoxShape(chimney.chimneyFront);
            chimneyFront = new Box(CalculateBoxPosition(chimney.chimneyFront), shape.X, shape.Y, shape.Z);
            space.Add(chimneyFront);

            shape = CalcuateBoxShape(chimney.chimneyBack);
            chimneyBack = new Box(CalculateBoxPosition(chimney.chimneyBack), shape.X, shape.Y, shape.Z);
            space.Add(chimneyBack);
        }
        

        
        private Vector3 CalcuateBoxShape(BoundingBox bb)
        {
            float halfX, halfY, halfZ;
            halfX = Math.Abs(bb.Min.X - bb.Max.X);// / 2.0f;
            halfY = Math.Abs(bb.Min.Y - bb.Max.Y);// / 2.0f;
            halfZ = Math.Abs(bb.Min.Z - bb.Max.Z);// / 2.0f;
            return new Vector3(halfX, halfY, halfZ);
        }

        private Vector3 CalculateBoxPosition(BoundingBox bb)
        {
            float x, y, z;
            x = (bb.Min.X + bb.Max.X) / 2.0f;
            y = (bb.Min.Y + bb.Max.Y) / 2.0f;
            z = (bb.Min.Z + bb.Max.Z) / 2.0f;
            return new Vector3(x, y, z);
        }

        

        #endregion
    }
}
